package com.example.web.security;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.common.utils.PublicUtil;
import com.example.entity.domain.MpShiroPermsInfo;
import com.example.entity.domain.MpSocialInfo;
import com.example.entity.domain.MpUserInfo;
import com.example.entity.mapper.MpShiroPermsInfoMapper;
import com.example.entity.mapper.MpSocialInfoMapper;
import com.example.entity.mapper.MpUserInfoMapper;
import com.example.security.domain.ShiroUserDetail;
import com.example.security.exception.PrefixNotFoundException;
import com.example.security.exception.SocialUserNotFoundException;
import com.example.security.properties.CompanyProperties;
import com.example.security.provider.ShiroUserDetailService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Author: lex
 * @Date: 2019/2/1
 */
@Component
@Slf4j
public class ShiroUserDetailServiceImpl implements ShiroUserDetailService {

    @Autowired
    private MpUserInfoMapper mpUserInfoMapper;

    @Autowired
    private MpSocialInfoMapper mpSocialInfoMapper;

    @Autowired
    private MpShiroPermsInfoMapper mpShiroPermsInfoMapper;

    @Autowired
    private CompanyProperties companyProperties;

    @Override
    public ShiroUserDetail getByMobile(String mobile) throws AuthenticationException {
        MpUserInfo mpUserInfo = mpUserInfoMapper.selectOne(new QueryWrapper<MpUserInfo>().eq("mobile", mobile));
        if (PublicUtil.isEmpty(mpUserInfo)) {
            log.error("未找到与该手机号相关联的用户 :mobile=[ {} ]", mobile);
            throw new AccountException("未找到与该手机号相关联的用户");
        }
        return this.filling(mpUserInfo);
    }

    @Override
    public ShiroUserDetail getByUserName(String username) throws AuthenticationException {
        MpUserInfo mpUserInfo = mpUserInfoMapper.selectOne(new QueryWrapper<MpUserInfo>().eq("username", username));
        if (PublicUtil.isEmpty(mpUserInfo)) {
            log.error("未找到该用户名对应的用户 :username=[ {} ]", username);
            throw new AccountException("未找到该用户名对应的用户");
        }
        return this.filling(mpUserInfo);
    }

    @Override
    public ShiroUserDetail getBySocialProvider(String itemId, String socialProviderId) throws AuthenticationException {
        String[] split = socialProviderId.split(":" + companyProperties.getLoginSplit() + ":");
        if (split.length!=2) {
            throw new PrefixNotFoundException("社交登入,没有分隔符");
        }
        String social = split[0]; // openId/unionId
        String socialUnderLine = PublicUtil.underline(new StringBuffer(social)).toString();
        String providerId = split[1]; //wx/qq
        log.warn("社交登入中的: social= [ {} 登入,主体为 {} ],providerId=[ {} ]", social,itemId, providerId);
        List<MpSocialInfo> mpSocialInfos = mpSocialInfoMapper.selectList(
                new QueryWrapper<MpSocialInfo>().eq(socialUnderLine, itemId).eq("provider_id", providerId));
        if (PublicUtil.isEmpty(mpSocialInfos)) {
            log.error("未找到社交登入的账号 :social=[ {} ],providerId=[ {} ]", social, providerId);
            throw new SocialUserNotFoundException("未找到对应的社交登入记录");
        }
        long userId = Long.parseLong(mpSocialInfos.iterator().next().getUserId());
        MpUserInfo mpUserInfo = mpUserInfoMapper.selectById(userId);
        return this.filling(mpUserInfo);
    }

    private ShiroUserDetail filling(MpUserInfo mpUserInfo) throws AuthenticationException {
        List<MpShiroPermsInfo> mpShiroPermsInfos = mpShiroPermsInfoMapper.selectList(new QueryWrapper<MpShiroPermsInfo>().eq("user_id", mpUserInfo.getId()));
        List<String> perms = Lists.newArrayList();
        if (PublicUtil.isNotEmpty(mpShiroPermsInfos)) {
            mpShiroPermsInfos.forEach(obj -> perms.add(obj.getPerms()));
            mpUserInfo.setPerms(perms);
            mpUserInfo.setMpShiroPermsInfoList(mpShiroPermsInfos);
        }
        log.warn("数据库查询成功 登入用户为 userId=[ {} ],用户名为:[ {} ]", mpUserInfo.getId().toString(), mpUserInfo.getUsername());
        log.warn("shiro框架识别用户名成功 < ================= < ============== < ");
        return new ShiroUserDetail(mpUserInfo.getId().toString(), mpUserInfo.getUsername(), mpUserInfo.getPassword(), mpUserInfo.getPerms());
    }
}
